#include <QDebug>
#include <QMessageBox>
#include <QStandardItemModel>
#include <QProcess>
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "ewha.h"
#include "DataHelper.h"
#include "ConfigDialog.h"
#include "SettingHelper.h"
#include "ProgressRing.h"

MainWindow::MainWindow(QWidget *parent) :
	QMainWindow(parent),
	ui(new Ui::MainWindow), m_iPatientID(-1), m_iTeethPosition(-1), m_pConsole(0),
	m_pProgressWidget(new ProgressRing(this)),
	m_iVoltage(0), m_iCurrent(0), m_iTime(0)
{
	ui->setupUi(this);

	this->registerMessage();
	this->makeActionList();
	this->connectSignalSlot();

	bool b;
	SettingHelper::loadFullScreen(b);

	if(b) this->showFullScreen();

	this->SlotChangeModStart();
}

MainWindow::~MainWindow()
{
	delete ui;
}

bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
	MSG *pMSG = (MSG*)message;

	if(pMSG->message == m_msgID[eMSGStandbyDone])
	{
		ui->pageConfigCapture->SlotStandbyDone();
	}
	else if(pMSG->message == m_msgID[eMSGReadyDone])
	{
		ui->pageConfigCapture->SlotReadyDone();
	}
	else if(pMSG->message == m_msgID[eMSGEXPOON])
	{
		ui->pageConfigCapture->SlotEXPOON();
	}
	else if(pMSG->message == m_msgID[eMSGEXPOOFF])
	{
		ui->pageConfigCapture->SlotEXPOOFF();
	}
	else if(pMSG->message == m_msgID[eMSGIMGDone])
	{
		ui->pageConfigCapture->SlotIMGDone();
	}
	else if(pMSG->message == m_msgID[eMSGError])
	{
		this->SlotSendClose();
		ui->pageConfigCapture->SlotError();
	}

	return false;
}

void MainWindow::initStateMachine()
{
	m_pStateInitial = new QState(m_pStateMachine);
	m_pStatePatient = new QState(m_pStateMachine);
	m_pStateFinal = new QFinalState(m_pStateMachine);
}

void MainWindow::connectSignalSlot()
{
	connect(ui->patientInfoInput, SIGNAL(SignalSearch(SPatient&)), SLOT(SlotSearchPatient(SPatient&)));
	connect(ui->patientInfoInput, SIGNAL(SignalRegister(SPatient&)), SLOT(SlotRegisterPatient(SPatient&)));
	connect(ui->pagePatientList, SIGNAL(SignalSelectedPatient(int)), SLOT(SlotSelectedPatient(int)));
	connect(ui->pageCaptureDateList, SIGNAL(SignalSelectedCaptureDate(QDate)), SLOT(SlotSelectCaptureDate(QDate)));
	connect(ui->pageConfigCapture, SIGNAL(SignalMessage(QString)), SLOT(SlotMessage(QString)));
	connect(ui->pageConfigCapture, SIGNAL(SignalControlValue(int,int,int)), SLOT(SlotControlValue(int,int,int)));
	connect(ui->pageConfigCapture, SIGNAL(SignalStartConsole()), SLOT(SlotStartConsole()));
	connect(ui->pageConfigCapture, SIGNAL(SignalSendStandby()), SLOT(SlotSendStandby()));
	connect(ui->pageConfigCapture, SIGNAL(SignalSendReady()), SLOT(SlotSendReady()));
	connect(ui->pageConfigCapture, SIGNAL(SignalSelectedTeeth(int)), SLOT(SlotSelectedTeeth(int)));
	connect(ui->pageConfigCapture, SIGNAL(SignalJustCaptured(QString)), SLOT(SlotJustCaptured(QString)));
	connect(ui->pageConfigCapture, SIGNAL(SignalJustCaptured(QString)), SLOT(SlotChangeModPreviewCapture()));
	connect(ui->pageConfigCapture, SIGNAL(SignalExitCapture()), SLOT(SlotSendClose()));
	connect(ui->pageConfigCapture, SIGNAL(SignalExitCapture()), SLOT(SlotChangeModViewImage()));
	connect(ui->pageConfigCapture, SIGNAL(SignalProgressStart()), m_pProgressWidget, SLOT(SlotProgressStart()));
	connect(ui->pageConfigCapture, SIGNAL(SignalProgressEnd()), m_pProgressWidget, SLOT(SlotProgressEnd()));
	connect(ui->pagePreviewCapture, SIGNAL(SignalCaptureMore()), SLOT(SlotCaptureMore()));
	connect(ui->pagePreviewCapture, SIGNAL(SignalCaptureProcessEnd()), SLOT(SlotCaptureProcessEnd()));
	connect(ui->pagePreviewCapture, SIGNAL(SignalCaptureProcessEnd()), SLOT(SlotSendClose()));
	connect(ui->pagePreviewCapture, SIGNAL(SignalNewCapture()), SLOT(SlotNewCapture()));
	connect(ui->pageWindowingTool, SIGNAL(SignalWindowing(int,int)), ui->pageViewImage, SIGNAL(SignalWindowing(int,int)));
	connect(ui->pageGammaTool, SIGNAL(SignalGamma(int)), ui->pageViewImage, SIGNAL(SignalGamma(int)));
	connect(ui->pageDrawTool, SIGNAL(SignalClickTool(ETool)), SIGNAL(SignalSetTool(ETool)));
	connect(this, SIGNAL(SignalSetTool(ETool)), ui->pageViewImage, SIGNAL(SignalSetTool(ETool)));
	connect(ui->pageViewImage, SIGNAL(SignalWindowingValue(int,int,int,int)), ui->pageWindowingTool, SLOT(SlotSetControl(int,int,int,int)));
	connect(ui->pageViewImage, SIGNAL(SignalHistogramData(QMap<int,int>)), ui->pageHistogramTool, SIGNAL(SignalHistogramData(QMap<int,int>)));
	connect(ui->pageViewImage, SIGNAL(SignalProfileDraw(QList<int>)), ui->pageProfileTool, SIGNAL(SignalProfileDraw(QList<int>)));
	connect(ui->actionSave, SIGNAL(triggered()), ui->pageViewImage, SIGNAL(SignalSaveImage()));
	connect(ui->actionDiagnosis, SIGNAL(triggered()), ui->pageViewImage, SIGNAL(SignalSaveDiagnosis()));
	connect(ui->actionDiagnosis, SIGNAL(triggered()), SLOT(SlotDiagnosis()));
	connect(ui->actionConfig, SIGNAL(triggered()), SLOT(SlotConfig()));
	connect(ui->pageViewImage, SIGNAL(SignalHistory(QAction*,QAction*)), SLOT(SlotHistory(QAction*,QAction*)));
}

void MainWindow::changeStackMainIndex(int iIndex)
{
	ui->stwMain->setCurrentIndex(iIndex);
}

void MainWindow::changeStackLargeWorkareaIndex(int iIndex)
{
	ui->stwLargeWorkarea->setCurrentIndex(iIndex);
}

void MainWindow::changeStackSmallWorkareaIndex(int iIndex)
{
	ui->stwSmallWorkarea->setCurrentIndex(iIndex);
}

void MainWindow::SlotChangeModStart()
{
	this->changeStackMainIndex(eInitial);
	this->setActionEnable(QList<EAction>() << eActPatient);
}

void MainWindow::SlotChangeModSearchRegister()
{
	this->changeStackMainIndex(ePatientInfoInput);
	this->setActionEnable(QList<EAction>() << eActPatient);
	qDebug() << "[OSK]";
	m_procOSK.start("C:/Windows/System32/osk.exe");
	qDebug() << m_procOSK.state() << m_procOSK.errorString();
	HWND hwnd = (HWND)m_procOSK.processId();
	RECT rc;
	GetWindowRect(hwnd, &rc);
	QRect rect(this->rect());
	int top = rect.height() - rc.bottom - rc.top;
	int left = (rect.width() - rc.right - rc.left) / 2;
	MoveWindow(hwnd, left, top, rc.right-rc.left, rc.bottom-rc.top, true);
	ui->patientInfoInput->initField();
}

void MainWindow::SlotChangeModSearchResult()
{
	if(m_procOSK.state() == QProcess::Running) m_procOSK.close();
	this->changeStackMainIndex(eWorkarea);
	this->changeStackLargeWorkareaIndex(ePatientList);
	this->changeStackSmallWorkareaIndex(eEmpty);
	this->setActionEnable(QList<EAction>() << eActPatient);
}

void MainWindow::SlotChangeModCapturedateList()
{
	this->changeStackSmallWorkareaIndex(eCapturedateList);
	this->setActionEnable(QList<EAction>() << eActPatient << eActCapture);
}

void MainWindow::SlotChangeModViewImage()
{
	this->changeStackLargeWorkareaIndex(eViewImage);
	this->setActionDisable(QList<EAction>() << eActSave);
}

void MainWindow::SlotChangeModWindowingTool()
{
	this->changeStackSmallWorkareaIndex(eWindowingTool);
	this->setActionEnableAll();
}

void MainWindow::SlotChangeModDrawTool()
{
	this->changeStackSmallWorkareaIndex(eDrawTool);
	this->setActionEnableAll();
}

void MainWindow::SlotChangeModGammaTool()
{
	this->changeStackSmallWorkareaIndex(eGammaTool);
	this->setActionEnableAll();
}

void MainWindow::SlotChangeModHistogramTool()
{
	this->changeStackSmallWorkareaIndex(eHistogramTool);
	this->setActionEnableAll();
}

void MainWindow::SlotChangeModProfileTool()
{
	this->changeStackSmallWorkareaIndex(eProfileTool);
	this->setActionEnableAll();

	emit SignalSetTool(eToolProfile);
}

void MainWindow::SlotChangeModConfigCapture()
{
	ui->pageConfigCapture->reset();
	this->changeStackLargeWorkareaIndex(eConfigCapture);
	this->setActionEnable(QList<EAction>() << eActPatient);
}

void MainWindow::SlotChangeModPreviewCapture()
{
	ui->pagePreviewCapture->setPreview(m_strCaptureFilePath);
	this->changeStackLargeWorkareaIndex(ePreviewCapture);
	this->setActionEnable(QList<EAction>() << eActPatient);
}

void MainWindow::SlotSearchPatient(SPatient &patient)
{
	this->searchPatient(patient);
}

void MainWindow::SlotRegisterPatient(SPatient &patient)
{
	if(QMessageBox::question(this, "EWHA",
						  "등록하시겠습니까?",
						  QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)
	   == QMessageBox::Yes)
	{
		if(!this->existPatient(patient))
		{
			if(this->registerPatient(patient)) this->SlotSearchPatient(patient);
			else
			{
				QMessageBox msg;

				msg.setIcon(QMessageBox::Information);
				msg.setText("DB 오류");
				msg.exec();
			}
		}
		else
		{
			QMessageBox msg;

			msg.setIcon(QMessageBox::Information);
			msg.setText("동일 환자가 있습니다");
			msg.exec();
		}
	}
	else {}
}

///
/// \brief MainWindow::SlotSelectPatient 환자 검색 목록에서 항목 클릭시 동작. 좌상단에 환자 정보 표시, 좌하단에 환자 촬영정보 표시
/// \param index
///
void MainWindow::SlotSelectedPatient(int iPatientID)
{
	m_iPatientID = iPatientID;

	DataHelper dbHelper;
	SPatient patient = dbHelper.getChart(m_iPatientID);

	ui->patientInfo->setPatientInfo(patient);

	QList<SCapturePerDate> listCapture = dbHelper.searchCapturePerDay(patient.m_iID);

	ui->pageCaptureDateList->setCaptureDateList(listCapture);
	this->SlotChangeModCapturedateList();
}

void MainWindow::SlotSelectCaptureDate(QDate dateCapture)
{
	QList<SCapture> listCapture(DataHelper().searchCapture(m_iPatientID, dateCapture));
	QString savePath;
	SettingHelper::loadImagePath(&savePath);
	QDir dir(savePath);

	for (int index = 0; index < listCapture.count(); ++index)
	{
		SCapture capture = listCapture[index];

		capture.m_strFilepath = QFileInfo(dir, capture.m_strFilepath).absoluteFilePath();
		listCapture[index] = capture;
	}

	ui->pageViewImage->setCaptureList(listCapture);
	this->SlotChangeModViewImage();
}

void MainWindow::SlotNewCapture()
{
	SCapture capture;
	QDateTime dt(QDateTime::currentDateTime());

	capture.m_iPatientID = m_iPatientID;
	capture.m_iPosition = m_iTeethPosition;
	capture.m_strFilepath = m_strCaptureFilePath;
	capture.m_dtCapture = dt;

	QString savePath;
	SettingHelper::loadImagePath(&savePath);
	QDir fiSaveDir(savePath);
	QFileInfo fiTempFile(m_strCaptureFilePath);

	if(fiSaveDir.exists() && fiTempFile.exists() && fiTempFile.isFile())
	{
		QFileInfo fi(QDir(QFileInfo(fiSaveDir, QString::number(m_iPatientID)).absoluteFilePath()), dt.toString("yyyyMMddhhmmss.%1").arg("raw"));
		fi.dir().mkpath(".");
		bool bCopy(QFile::copy(fiTempFile.absoluteFilePath(), fi.absoluteFilePath()));
		qDebug() << "[file copy]" << bCopy << fiTempFile.absoluteFilePath() << fi.absoluteFilePath();
		if(bCopy)
		{
			capture.m_strFilepath = fi.absoluteFilePath().remove(0, fiSaveDir.absolutePath().length());
			if(capture.m_strFilepath.indexOf('/', 0) == 0) capture.m_strFilepath.remove(0, 1);
			DataHelper().newCapture(capture);
		}
	}
}

void MainWindow::SlotJustCaptured(const QString &strFilePath)
{
	qDebug() << "capture file" << strFilePath;
	m_strCaptureFilePath = strFilePath;
}

void MainWindow::SlotSelectedTeeth(int iTeethIndex)
{
	m_iTeethPosition = iTeethIndex;
}

void MainWindow::SlotCaptureProcessEnd()
{
	this->SlotSelectedPatient(m_iPatientID); //추가된 촬영 항목 갱신을 위함
	this->SlotChangeModViewImage();
}

void MainWindow::SlotCaptureMore()
{
	this->SlotSelectedPatient(m_iPatientID);
	this->SlotChangeModConfigCapture();
}

void MainWindow::SlotConfig()
{
	ConfigDialog dlg(this);
	dlg.exec();
}

void MainWindow::SlotHistory(QAction *pUndo, QAction *pRedo)
{
	ui->mainToolBar->removeAction(ui->mainToolBar->actions().at(3));
	ui->mainToolBar->removeAction(ui->mainToolBar->actions().at(3));

	if(pUndo != NULL && pRedo != NULL)
	{
		QIcon iconUndo;
		QIcon iconRedo;

		iconUndo.addFile(QStringLiteral(":/resource/image/00_menu_btn_undo_normal.png"), QSize(), QIcon::Normal, QIcon::On);
		iconUndo.addFile(QStringLiteral(":/resource/image/00_menu_btn_undo_disable.png"), QSize(), QIcon::Disabled, QIcon::On);
		iconUndo.addFile(QStringLiteral(":/resource/image/00_menu_btn_undo_press.png"), QSize(), QIcon::Active, QIcon::On);
		iconUndo.addFile(QStringLiteral(":/resource/image/00_menu_btn_undo_select.png"), QSize(), QIcon::Selected, QIcon::On);
		iconRedo.addFile(QStringLiteral(":/resource/image/00_menu_btn_redo_normal.png"), QSize(), QIcon::Normal, QIcon::On);
		iconRedo.addFile(QStringLiteral(":/resource/image/00_menu_btn_redo_disable.png"), QSize(), QIcon::Disabled, QIcon::On);
		iconRedo.addFile(QStringLiteral(":/resource/image/00_menu_btn_redo_press.png"), QSize(), QIcon::Active, QIcon::On);
		iconRedo.addFile(QStringLiteral(":/resource/image/00_menu_btn_redo_select.png"), QSize(), QIcon::Selected, QIcon::On);
		pUndo->setIcon(iconUndo);
		pRedo->setIcon(iconRedo);
		ui->mainToolBar->insertAction(ui->mainToolBar->actions().at(3), pRedo);
		ui->mainToolBar->insertAction(pRedo, pUndo);
	}
	else
	{
		ui->mainToolBar->insertAction(ui->mainToolBar->actions().at(3), ui->actionRedo);
		ui->mainToolBar->insertAction(ui->actionRedo, ui->actionUndo);
	}
}

void MainWindow::SlotDiagnosis()
{
	QString strExePath, strSaveExt;
	SettingHelper::loadDiagnosis(&strExePath, &strSaveExt);
	QFileInfo fi(strExePath);

	if(fi.exists() && fi.isFile())
	{
		QProcess::startDetached(strExePath);
	}
}

void MainWindow::SlotMessage(const QString &strMessage)
{
	ui->stateInfo->setInfo(strMessage);
}

void MainWindow::SlotStartConsole()
{
	if(!m_pConsole)
	{
		QString exePath;
		SettingHelper::loadConsole(&exePath);
		m_pConsole = new ConsoleWrapper(exePath, this);
	}

	m_pConsole->SlotStart();
}

void MainWindow::SlotSendStandby()
{
	if(m_pConsole) m_pConsole->sendMessage(m_msgID[eMSGStandby], m_iTime, m_iCurrent);
}

void MainWindow::SlotSendReady()
{
	if(m_pConsole) m_pConsole->sendMessage(m_msgID[eMSGReady]);
}

void MainWindow::SlotSendClose()
{
	if(m_pConsole) m_pConsole->sendMessage(m_msgID[eMSGClose]);
}

void MainWindow::SlotControlValue(int iVoltage, int iCurrent, int iTime)
{
	m_iVoltage = iVoltage;
	m_iCurrent = iCurrent;
	m_iTime = iTime;
}

void MainWindow::searchPatient(SPatient &patient)
{
	QList<SPatient> listPatient = DataHelper().searchChart(patient);

	if(!listPatient.isEmpty())
	{
		ui->pagePatientList->setPatientList(listPatient);
		this->changeStackMainIndex(eWorkarea);
		this->SlotChangeModSearchResult();
	}
	else
	{
		QMessageBox msg;

		msg.setIcon(QMessageBox::Information);
		msg.setText("검색결과 없음");
		msg.exec();
	}
}

bool MainWindow::registerPatient(SPatient &patient) const
{
	return DataHelper().newChart(patient);
}

bool MainWindow::existPatient(const SPatient &patient) const
{
	return DataHelper().existPatient(patient);
}

void MainWindow::setActionEnable(QList<EAction> listAct)
{
	foreach (QAction *pAct, m_listAct)
	{
		pAct->setDisabled(true);
	}

	foreach (EAction eAct, listAct)
	{
		m_listAct[eAct]->setEnabled(true);
	}
}

void MainWindow::setActionEnableAll()
{
	foreach (QAction *pAct, m_listAct)
	{
		pAct->setEnabled(true);
	}
}

void MainWindow::setActionDisable(QList<EAction> listAct)
{
	foreach (QAction *pAct, m_listAct)
	{
		pAct->setEnabled(true);
	}

	foreach (EAction eAct, listAct)
	{
		m_listAct[eAct]->setDisabled(true);
	}
}

void MainWindow::registerMessage()
{
	m_msgID[eMSGStandby] = RegisterWindowMessage(L"Standby");
	m_msgID[eMSGStandbyDone] = RegisterWindowMessage(L"StandbyDone");
	m_msgID[eMSGReady] = RegisterWindowMessage(L"Ready");
	m_msgID[eMSGReadyDone] = RegisterWindowMessage(L"ReadyDone");
	m_msgID[eMSGEXPOON] = RegisterWindowMessage(L"EXPOON");
	m_msgID[eMSGEXPOOFF] = RegisterWindowMessage(L"EXPOOFF");
	m_msgID[eMSGIMGDone] = RegisterWindowMessage(L"IMGDone");
	m_msgID[eMSGClose] = RegisterWindowMessage(L"Close");
	m_msgID[eMSGError] = RegisterWindowMessage(L"Error");
}

void MainWindow::makeActionList()
{
	m_listAct << ui->actionPatient << ui->actionCapture << ui->actionSave <<
				 ui->actionDiagnosis << ui->actionDraw << ui->actionHistogram <<
				 ui->actionProfile << ui->actionWindowing << ui->actionGamma;
}
